import java.util.*;

public class demo {
    // 电话号码▲▲▲
//电话的九宫格，如你所见一个数字对应一些字母，因此在国外企业喜欢把电话号码设计成与自己公司名字相对应。例如公司的Help Desk号码是4357，
//因为4对应H、3对应E、5对应L、7对应P，因此4357就是HELP。同理，TUT-GLOP就代表888-4567、310-GINO代表310-4466。
//NowCoder刚进入外企，并不习惯这样的命名方式，现在给你一串电话号码列表，请你帮他转换成数字形式的号码，并去除重复的部分。
//        输入描述:
//      输入包含多组数据。
//      每组数据第一行包含一个正整数n（1≤n≤1024）。
//      紧接着n行，每行包含一个电话号码，电话号码仅由连字符“-”、数字和大写字母组成。
//      没有连续出现的连字符，并且排除连字符后长度始终为7（美国电话号码只有7位）。
//        输出描述:
//      对应每一组输入，按照字典顺序输出不重复的标准数字形式电话号码，即“xxx-xxxx”形式。
//      每个电话号码占一行，每组数据之后输出一个空行作为间隔符。


//输入
//12
//4873279
//ITS-EASY
//888-4567
//3-10-10-10
//888-GLOP
//TUT-GLOP
//967-11-11
//310-GINO
//F101010
//888-1200
//-4-8-7-3-2-7-9-
//487-3279
//4
//UTT-HELP
//TUT-GLOP
//310-GINO
//000-1213

    //输出
//310-1010
//310-4466
//487-3279
//888-1200
//888-4567
//967-1111
//
//000-1213
//310-4466
//888-4357
//888-4567
//    注:Set排序
//set包括HashSet和TreeSet，HashSet是基于HashMap的，TreeSet是基于TreeMap的。
//TreeMap是用红黑树实现，天然就具有排序功能，“天然就具有排序功能”是指它拥有升序、降序的迭代器。
//那么HashSet怎么排序呢？我们可以将HashSet转成List，然后用List进行排序。
    // 所以该题我们使用TreeSet()
    public static void main1(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 两个字符串对应转换
        String sysTem = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        String number = "222333444555666777788899991234567890";
        while (sc.hasNext()) {
            int n = sc.nextInt();
            // 因为多组输入 所以set要创建在循环内部 每次循环都需要new一个新的set
            Set<String> set = new HashSet<>();
            for (int i=0; i<n; i++) {
                // 先将输入的字符串中的 "-" 去掉
                String str = sc.next().replace("-", "");
                // 保存转换的字符
                StringBuffer sb = new StringBuffer();

                // 因为题意固定7个字符
                for (int j=0; j<7; j++) {
                    if (j == 3) {//格式
                        sb.append("-");
                    }
                    char ch = str.charAt(j);
                    int dex = sysTem.indexOf(ch);
                    sb.append(number.charAt(dex));
                }
                set.add(new String(sb));
            }

            // 打印
            for (String e:set) {
                System.out.println(e);
            }
            System.out.println();
        }
    }



    // 求和▲▲▲▲▲▲
//    输入两个整数 n 和 m，从数列1，2，3.......n 中随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来
//                  输入
//              5 5
//                  输出
//              1 4
//              2 3
//              5
//    1 2 3 4 5          5
//    1<5
//    1+2<5
//    1+2+3<5 err
//    1+2+4<5 err...
//    1+3<5
//    1+4=5 保存打印


    //思路:
//递归中每次累加一个新的数，如果累加和大于等于目标，结束递归。此时如果累加和正好等于目标，则打印
//组合。向上回退，搜索其它组合。此题本身就是一个搜索的过程，找到所有的组合。
//    list保存满足累加和等于m的数   pos表示当前位置   最开始pos等于1
//    sum表示累加和
    public static void getSum(List<Integer> list, int pos, int sum, int n, int m) {
        // 先判断 递归结束条件
        if (sum >= m) {
            // 我们要注意 当sum==m时 是我们需要的值 否则return出去
            // 因为 打印结束时我们要换行 所以最后一个值我们需要单独打印
            if (sum == m) {
                for (int i=0; i<list.size()-1; i++) {
                    System.out.print(list.get(i) + " ");//注意格式
                }
                System.out.println(list.get(list.size()-1));
            }
            // 因为数列是递增的 当sum已经大于m了 后面sum也一定大于m 所以不必再调用一遍 直接return出去
            return;
        }

        // 到这一步 是sum小于m
        // 为什么i=pos 因为 在累加过程中 每个数只能用一次 我们也是递增方式进行累加的
        // 这里i<=n 因为也包括n这个数字
        for (int i=pos; i<=n; i++) {
            // 我们先将累加的数 保存到链表中
            list.add(i);
            //递归 看是否需要在添加下一个数 pos位置 参数是i+1  我们是加是递增往后加的
            getSum(list, i+1, sum+i, n, m);

            // 如果走到这 说明 sum>=m了 所以我们需要回退将 保存到list中的最后一个值删除掉
            list.remove(list.size()-1);
        }
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNextInt()) {
            int n = sc.nextInt();
            int m = sc.nextInt();
            List<Integer> list = new ArrayList<>();
            int sum = 0;
            getSum(list, 1, sum, n, m);
        }
    }
}
